package chan.project.manager;

import chan.project.common.ErrorCode;
import chan.project.config.CosClientConfig;
import chan.project.exception.BusinessException;
import chan.project.exception.ThrowUtils;
import chan.project.model.dto.file.UploadPictureResult;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.*;
import com.qcloud.cos.COSClient;
import com.qcloud.cos.model.PutObjectRequest;
import com.qcloud.cos.model.PutObjectResult;
import com.qcloud.cos.model.ciModel.persistence.ImageInfo;
import com.qcloud.cos.model.ciModel.persistence.PicOperations;
import lombok.extern.slf4j.Slf4j;
import net.bytebuddy.implementation.bytecode.Throw;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.util.StringUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Arrays;
import java.util.Date;
import java.util.List;

/**
 * 已经优化为模板方法模式，在chan.project.template包下
 */
@Deprecated
@Slf4j
@Component
public class FileManager {

    @Resource
    private CosManager cosManager;

    @Resource
    private CosClientConfig cosClientConfig;

    /**
     * 上传图片并校验
     * @param multipartFile 文件
     * @param uploadPathPreFix 文件存储前缀
     * @return 返回图片信息
     */
    public UploadPictureResult uploadPicture(MultipartFile multipartFile,String uploadPathPreFix){
        validFile(multipartFile);
        //图片存储的名称是时间戳+uuid+文件后缀
        String uuid = RandomUtil.randomString(16);
        String originalFilename = multipartFile.getOriginalFilename();
        String uploadFileName = String.format("%s_%s.%s", DateUtil.formatDate(new Date()), uuid, FileUtil.getSuffix(originalFilename));
        //文件路径是文件传输的前缀/文件名称
        String filePath = String.format("/%s/%s", uploadPathPreFix, uploadFileName);
        File file = null;
        try {
            //创建临时文件
            file = File.createTempFile(filePath,null);
            multipartFile.transferTo(file);
            //上传文件
            PutObjectResult putObjectResult = cosManager.putPictureObject(filePath, file);
            ImageInfo imageInfo = putObjectResult.getCiUploadResult().getOriginalInfo().getImageInfo();
            //封装返回结果
            UploadPictureResult uploadPictureResult = new UploadPictureResult();
            int picWidth = imageInfo.getWidth();
            int picHeight = imageInfo.getHeight();
            double picScale = NumberUtil.round(picWidth * 1.0 / picHeight,2).doubleValue();
            uploadPictureResult.setPicName(FileUtil.mainName(originalFilename));
            uploadPictureResult.setPicSize(FileUtil.size(file));
            uploadPictureResult.setPicWidth(picWidth);
            uploadPictureResult.setPicHeight(picHeight);
            uploadPictureResult.setPicScale(picScale);
            uploadPictureResult.setPicFormat(imageInfo.getFormat());
            uploadPictureResult.setUrl(cosClientConfig.getHost() + "/" + filePath);
            return uploadPictureResult;
        } catch (IOException e) {
            log.error("上传失败");
            throw new RuntimeException(e);
        } finally {
            deleteFile(file);
        }
    }

    /**
     * 通过url上传图片
     * @param url
     * @param uploadPathPreFix
     */
    public UploadPictureResult uploadPictureByUrl(String url, String uploadPathPreFix){
        validFile(url);
        //图片存储的名称是时间戳+uuid+文件后缀
        String uuid = RandomUtil.randomString(16);
        String originalFilename = FileUtil.mainName(url);
        String uploadFileName = String.format("%s_%s.%s", DateUtil.formatDate(new Date()), uuid, FileUtil.getSuffix(originalFilename));
        //文件路径是文件传输的前缀/文件名称
        String filePath = String.format("/%s/%s", uploadPathPreFix, uploadFileName);
        File file = null;
        try {
            //创建临时文件
            file = File.createTempFile(filePath,null);
            HttpUtil.downloadFile(url,file);
            //上传文件
            PutObjectResult putObjectResult = cosManager.putPictureObject(filePath, file);
            ImageInfo imageInfo = putObjectResult.getCiUploadResult().getOriginalInfo().getImageInfo();
            //封装返回结果
            UploadPictureResult uploadPictureResult = new UploadPictureResult();
            int picWidth = imageInfo.getWidth();
            int picHeight = imageInfo.getHeight();
            double picScale = NumberUtil.round(picWidth * 1.0 / picHeight,2).doubleValue();
            uploadPictureResult.setPicName(FileUtil.mainName(originalFilename));
            uploadPictureResult.setPicSize(FileUtil.size(file));
            uploadPictureResult.setPicWidth(picWidth);
            uploadPictureResult.setPicHeight(picHeight);
            uploadPictureResult.setPicScale(picScale);
            uploadPictureResult.setPicFormat(imageInfo.getFormat());
            uploadPictureResult.setUrl(cosClientConfig.getHost() + "/" + filePath);
            return uploadPictureResult;
        } catch (IOException e) {
            log.error("上传失败");
            throw new RuntimeException(e);

        } finally {
            deleteFile(file);
        }
    }

    /**
     * 图片检验
     * @param multipartFile
     * @return
     */
    public void validFile(MultipartFile multipartFile){
        //校验文件是否为空
        ThrowUtils.throwIf(multipartFile == null, ErrorCode.PARAMS_ERROR);
        //校验文件大小
        final long MAX = 10 * 1024 * 1024L;
        ThrowUtils.throwIf(multipartFile.getSize() > MAX,ErrorCode.PARAMS_ERROR,"文件大小不能超过10MB");
        //校验文件后缀
        String originalFilename = multipartFile.getOriginalFilename();
        final List<String> ALLOW_FORMAT_LIST = Arrays.asList("png", "jpeg", "jpg", "webp");
        ThrowUtils.throwIf(ALLOW_FORMAT_LIST.contains(originalFilename),ErrorCode.PARAMS_ERROR,"文件类型错误");
    }

    public void validFile(String url){
        ThrowUtils.throwIf(StringUtils.isNotBlank(url),ErrorCode.PARAMS_ERROR,"url为空");
        //1.验证url的正确性
        try {
            new URL(url);
        } catch (MalformedURLException e) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        //2.验证url协议
        ThrowUtils.throwIf(url.startsWith("http://") || url.startsWith("https://")
                ,ErrorCode.PARAMS_ERROR,"url协议错误");
        //3.验证文件是否存在
        try (HttpResponse response = HttpUtil.createRequest(Method.HEAD, url).execute()) {
            if (response.getStatus() != HttpStatus.HTTP_OK) {
                throw new BusinessException(ErrorCode.PARAMS_ERROR, "访问的url不正常");
            }
            String contentType = response.header("Content-Type");
            if (StringUtils.isNotBlank(contentType)) {
                final List<String> ALLOW_CONTENT_TYPES = Arrays.asList("image/png", "image/webp", "image/jpeg", "image/jpg");
                ThrowUtils.throwIf(!ALLOW_CONTENT_TYPES.contains(contentType.toLowerCase()), ErrorCode.PARAMS_ERROR, "文件类型错误");
            }
            //4.验证文件大小
            String contentLengthStr = response.header("Content-Length");
            if (StrUtil.isNotBlank(contentLengthStr)) {
                try {
                    long contentLength = Long.parseLong(contentLengthStr);
                    final long TWO_MB = 2 * 1024 * 1024L;
                    ThrowUtils.throwIf(contentLength > TWO_MB, ErrorCode.PARAMS_ERROR, "文件大小不能超过2MB");
                } catch (NumberFormatException e) {
                    throw new BusinessException(ErrorCode.PARAMS_ERROR, "文件大小超限");
                }
            }
        }

    }
    /**
     * 删除无用文件
     * @param file
     */
    public void deleteFile(File file){
        if(file == null){
            return;
        }
        boolean delete = file.delete();
        if(!delete){
            log.error("删除失败,请及时删除文件{}防止内存溢出",file.getAbsoluteFile());
        }
    }
}
